import { _net_date_encode } from "../NETGOBERTS";
import LengthOptimizeConfig from "./LengthOptimizeConfig";

const writeStrToBuffer = function (byteBuffer, strVal: string, startIndex: number) {
    const bufView = new DataView(byteBuffer, startIndex);
    for (let i = 0, strLen = strVal.length; i < strLen; ++i) {
        bufView.setUint8(i, strVal.charCodeAt(i));
    }
};
/**  cmdIndex(1)
 * + serviceAndMethodLen(1)
 * + serviceAndMethod(.length)
 * + userIdAndSessionKeyLength(1)
 * + userIdAndSessionKey(.length)
 * + protoNameLength(1)
 * + uintArray(.length)
 */
export default class ProtoEncoder {
    protoFileClsArray = {};
    len: LengthOptimizeConfig;
    constructor(len: LengthOptimizeConfig) {
        this.len = len;
        if (!this.len)
            this.len = new LengthOptimizeConfig();
    }
    encode(data: _net_date_encode) {
        const uintArray: Uint8Array = data.message.protoCls.encode(data.message).finish();
        const bytes = uintArray.buffer.slice(0, uintArray.length);
        const protoLength = bytes.byteLength;
        let protoName = data.protoName;
        const replaceProtoName = this.len.encoderProtoNameMap[protoName];
        if (replaceProtoName) {
            protoName = replaceProtoName;
        }
        const protoNameLength = protoName.length;
        let serviceAndMethod = data.serviceAndMethod;
        const replaceServiceAndMethod = this.len.encoderServiceNameMap[serviceAndMethod];
        if (replaceServiceAndMethod) {
            serviceAndMethod = replaceServiceAndMethod;
        }
        const serviceAndMethodLength = serviceAndMethod.length;
        const userIdAndSessionKey = "";
        const userIdAndSessionKeyLength = userIdAndSessionKey.length;
        const totalLength = 4 + 1 + serviceAndMethodLength + 1 + userIdAndSessionKeyLength + 1 + protoNameLength + protoLength;

        const byteBuffer = new ArrayBuffer(totalLength);
        const byteBufferView = new DataView(byteBuffer);
        byteBufferView.setUint32(0, data.cmdIndex, false);
        byteBufferView.setUint8(4, serviceAndMethodLength);
        writeStrToBuffer(byteBuffer, serviceAndMethod, 5);
        byteBufferView.setUint8(serviceAndMethodLength + 5, userIdAndSessionKeyLength);
        writeStrToBuffer(byteBuffer, userIdAndSessionKey, serviceAndMethodLength + 6);
        byteBufferView.setUint8(serviceAndMethodLength + userIdAndSessionKeyLength + 6, protoNameLength);
        writeStrToBuffer(byteBuffer, protoName, serviceAndMethodLength + userIdAndSessionKeyLength + 7);
        const startIndex = serviceAndMethodLength + userIdAndSessionKeyLength + protoNameLength + 7;
        for (let i = 0; i < protoLength; i++) {
            byteBufferView.setUint8(startIndex + i, uintArray[i]);
        }
        return byteBufferView.buffer;
    }
}